package minishell;

import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;

import org.lex.utils.Pair;
import org.lex.utils.text.Splitter;

import minishell.cmdlet.Cmdlet;
import minishell.cmdlet.buildin.PwdCmdlet;
import minishell.cmdlet.buildin.SpyCmdlet;
import minishell.object.IObject;
import minishell.object.format.ObjectFormatter;
import minishell.util.BuildinCmdlets;

public class CmdletHandler
{
	public static final String ERROR = "[ERROR] ";

	private PrintWriter writer = null;
	private Pattern semicolonSplitter = null;
	private Pattern pipeSplitter = null;

	public CmdletHandler( PrintWriter writer )
	{
		this.writer = writer;
		this.semicolonSplitter = Splitter.SemicolonSplitter;
		this.pipeSplitter = Splitter.PipeSplitter;
	}

	/**
	 * ������������������ԭʼ��ʽ�洢��String input��
	 * ע�⡰����ȿ���ʹ�򵥵ĵ������Ҳ�����Ǹ��ϵ����������
	 * 1)���ܵ������: ls|find txt
	 * 2)����";"�ֺŷָ����������
	 * @param input �����ָ��
	 */
	public void handle( String input )
	{
		String[] cmds = this.semicolonSplitter.split( input );
		if( 0 == cmds.length )
			return;
		//�ж��Ƿ���һ������
		if( 1 == cmds.length )
		{
			//����������,�����ǰ�ܵ�������
			this.handleSingleCmdlet( cmds[0] );
		}
		else
		{
			for( String cmd : cmds )
				if( null != cmd && 0 != cmd.trim().length() )
					this.handleSingleCmdlet( cmd );
		}
	}

	private void handleSingleCmdlet( String singleCommand )
	{
		String[] cmds = this.pipeSplitter.split( singleCommand );
		if( cmds.length > 1 )
		{
			this.handlePipedCmdlet( cmds );
			return;
		}
		Pair<String, String> p = this.split( singleCommand );
		if( true == BuildinCmdlets.isBuildinCmdlet( p.first() ) )
		{
			// handle build-in cmdlet
			Cmdlet cmd = BuildinCmdlets.getCmdlet( p.first() );
			if( null == cmd )
			{
				errorln( "cann't get '" + p.first() + "' instance" );
				return;
			}
			List<IObject> result = cmd.excute( p.second().trim() );
			this.printResult( cmd.getFormatter(), result );
		}
		else
		{
			errorln( "'" + p.first() + "' is not a build-in command" );
		}
	}

	private void handlePipedCmdlet( String[] cmds )
	{
		this.printResult( new SpyCmdlet( new PwdCmdlet().excute( "" ) ).excute( "" ) );
	}

	// ��ӡ
	private void printResult( List<IObject> list )
	{
		Iterator<IObject> result = list.iterator();
		while( result.hasNext() )
			this.println( String.valueOf( result.next().toString() ) );
	}

	private void printResult( ObjectFormatter formatter, List<IObject> list )
	{
		Iterator<IObject> result = list.iterator();
		while( result.hasNext() )
			this.println( formatter.format( result.next() ) );
	}

	private CmdletHandler print( String msg )
	{
		writer.print( msg );
		return this;
	}

	private CmdletHandler println( String msg )
	{
		writer.println( msg );
		return this;
	}

	private CmdletHandler error( String msg )
	{
		return this.print( ERROR ).print( msg );
	}

	private CmdletHandler errorln( String msg )
	{
		this.error( msg );
		return this.println( "" );
	}

	/*
	 * ������Ͳ���ָ���
	 * eg.: "ls -l" -> ( "ls", "-l" )
	 */
	Pair<String, String> split( String input )
	{
		StringBuilder buffer = new StringBuilder();
		int index = 0;
		// skip white-space
		while( index < input.length()
			&& true == Character.isWhitespace( input.charAt( index ) ) )
			index++;
		while( index < input.length()
			&& false == Character.isWhitespace( input.charAt( index ) ) )
			buffer.append( input.charAt( index++ ) );
		String name = buffer.toString();
		String arg = input.substring( index );
		return new Pair<String, String>( name, arg );
	}
}
